package trading.algo.BullToBearTask;

import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import trading.algo.OptionLmtOrderTask;
import trading.algo.OptionMktOrderTask;
import trading.algo.TimerKillerTask;
import trading.bo.DBAccessorBO;
import trading.bo.EmailAccessorBO;
import trading.bo.IBAccessorBO;
import trading.util.Constants;
import trading.util.OptionSpotPriceUtil;

public class ProtectionOrderCreationTask extends TimerTask{

	private DBAccessorBO dbAccessorBO;
	private IBAccessorBO ibAccessorBO;
	private EmailAccessorBO emailAccessorBO;
	private String expiry;
	private double strike;
	
	public ProtectionOrderCreationTask(DBAccessorBO dbAccessorBO, IBAccessorBO ibAccessorBO, EmailAccessorBO emailAccessorBO, String expiry, double strike) {
		this.dbAccessorBO = dbAccessorBO;
		this.ibAccessorBO = ibAccessorBO;
		this.emailAccessorBO = emailAccessorBO;
		this.expiry = expiry;
		this.strike = strike;
	}
	
	@Override
	public void run() {
		// Step 1: get latest option price
		double optionSpotPrice = OptionSpotPriceUtil.getPrice();
		OptionSpotPriceUtil.reset();
		// Step 2: calculate order size
		double netLiquidation = this.dbAccessorBO.getNetLiquidation();
		int orderSize = (int) (netLiquidation * 0.05/(optionSpotPrice * 100));
		
		Timer timer = new Timer();
		int taskID = 0;
		OptionMktOrderTask optionMktOrderTask = new OptionMktOrderTask(this.ibAccessorBO, emailAccessorBO, "BUY", orderSize, "MKT", Constants.VIX, expiry, strike, Constants.IB.CALL);
		timer.schedule(optionMktOrderTask, taskID * 1000);
		taskID++;
		// Step 3: create closing order
		Map<Integer, Double> closingOrderStat = calcClosingOrders(orderSize, optionSpotPrice);
		for (Integer size : closingOrderStat.keySet()) {
			OptionLmtOrderTask optionLmtOrderTask = new OptionLmtOrderTask(this.ibAccessorBO, emailAccessorBO, "SELL", size, "LMT", Constants.VIX, closingOrderStat.get(size), expiry, strike, Constants.IB.CALL);
		    timer.schedule(optionLmtOrderTask, taskID * 1000);
		    taskID++;
		}
		// Step 4: kill timer
		TimerKillerTask timerKillerTask = new TimerKillerTask(timer);
		timer.schedule(timerKillerTask, taskID * 1000);
	}
	
	/**
	 * A map of order size and limit price
	 * @return
	 */
	private Map<Integer, Double> calcClosingOrders(int totalOrderSize, double currentPrice) {
		Map<Integer, Double> closingOrders = new HashMap<Integer, Double>();
		int remainingSize = totalOrderSize;
		double lastLmtPrice = currentPrice;
		while (remainingSize > 0) {
			int batchSize = (int) (remainingSize * 0.7);
			double batchPrice = lastLmtPrice * 1.8;
			closingOrders.put(batchSize, batchPrice);
			remainingSize -= batchSize;
			lastLmtPrice = batchPrice;
		}
		return closingOrders;
	}


}
